package main

import (
	"fmt"
	"io"
	"strings"
)

/* 实现reader与一些例子 */

// func main() {
// 	// simpleReader()
// 	// demoChainReader()
// 	WriterDemo()
// }

// 普通reader
func simpleReader() {
	stringReader := strings.NewReader("hello the world")
	p := make([]byte, 4) // 直接定义长度
	for {
		n, err := stringReader.Read(p)
		if err != nil {
			if err == io.EOF {
				fmt.Println("get the EOF, ", string(p[:n]))
				break
			}
			// 其他错误
			fmt.Println(err)
			return
		}
		fmt.Println("the resource in p:", string(p[:n]))
	}
}

// 自定义reader -- 从资源中读取内容到缓冲区
type reader struct {
	data string // 存储resource数据
	cur  int    // 索引使用
}

// Reader的核心方法
func (r *reader) Read(b []byte) (int, error) {
	if r.cur >= len(r.data) { // 末尾
		return 0, io.EOF
	}
	if len(b) > len(r.data)-r.cur { // b的长度大于剩下的长度
		copy(b, []byte(r.data[r.cur:]))
		n := len(r.data) - r.cur
		r.cur = n
		return n, nil
	}

	// 插入处理逻辑

	n := len(b)
	copy(b, []byte(r.data[r.cur:r.cur+n]))
	r.cur += n
	return n, nil
}

func NewReader(s string) (*reader, error) {
	return &reader{
		data: s,
		cur:  0,
	}, nil
}

// 链式reader
// 使用读取器作为另一个读取器的源是一种常见的习语。读取器的这种链接允许一个读取器重用另一个读取器的逻辑
// 从某一个reader中读取数据，然后删掉其中非字母的字符
type AlphaReader struct {
	reader io.Reader
}

func NewAlphaReader(r io.Reader) (*AlphaReader, error) {
	return &AlphaReader{reader: r}, nil
}

func (a *AlphaReader) Read(b []byte) (int, error) {
	n, err := a.reader.Read(b) // 索引覆盖
	if nil != err {
		return n, err
	}
	temp := make([]byte, 0, n)
	for i := 0; i < n; i++ {
		if alpha(b[i]) {
			temp = append(temp, b[i])
		}
	}
	copy(b, temp)
	return n, nil
}

func alpha(r byte) bool {
	if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') {
		return true
	}
	return false
}

// func alpha(r byte) byte {
// 	if r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' {
// 		return r
// 	}
// 	return 0
// }

func demoChainReader() {
	// file, err := os.Open("./alpha_reader2.go")
	// if err != nil {
	//     fmt.Println(err)
	//     os.Exit(1)
	// }
	// defer file.Close()
	sReader, _ := NewReader("hello world123, this is demo3 , hdsaind3214455")
	a, err := NewAlphaReader(sReader)
	if nil != err {
		fmt.Println("NewAlphaReader error: ", err)
		return
	}
	p := make([]byte, 5)
	for i := 0; i < 10; i++ {
		n, err := a.Read(p)
		if io.EOF == err {
			break
		}
		fmt.Print(string(p[:n]))
	}
	fmt.Println()
}
